<!DOCTYPE html>
<html lang="cn">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>后台管理系统</title>
    <link rel="stylesheet" type="text/css" href="../../assets/lib/iview/styles/iview.css" />
    <link rel="stylesheet" type="text/css" href="../../assets/css/default.css" />
    <link rel="stylesheet" type="text/css" href="../../assets/lib/vue/plugins/org-tree.css" />
    <script src="../../assets/lib/vue/vue-2.5.17.min.js"></script>
    <script src="../../assets/lib/iview/iview.min.js"></script>
    <script src="../../assets/lib/axios/axios.min.js"></script>
    <script src="../../assets/lib/vue/plugins/org-tree.js"></script>
    <style>
      .percent-100 {
        width: 100%;
        height: 100%;
      }
      .department-outer {
        width: 100%;
        height: 100%;
        overflow: hidden;
      }
      .department-outer .tip-box {
        position: absolute;
        left: 20px;
        top: 20px;
        z-index: 12;
      }
      .department-outer .zoom-box {
        position: absolute;
        right: 30px;
        bottom: 30px;
        z-index: 2;
      }
      .department-outer .view-box {
        position: absolute;
        top: 0;
        bottom: 0;
        left: 0;
        right: 0;
        z-index: 1;
        cursor: move;
      }
      .department-outer .view-box .org-tree-drag-wrapper {
        width: 100%;
        height: 100%;
      }
      .department-outer .view-box .org-tree-wrapper {
        display: inline-block;
        position: absolute;
        left: 50%;
        top: 50%;
        -webkit-transition: -webkit-transform 0.2s ease-out;
        transition: -webkit-transform 0.2s ease-out;
        transition: transform 0.2s ease-out;
        transition: transform 0.2s ease-out, -webkit-transform 0.2s ease-out;
      }
      .department-outer .view-box .org-tree-wrapper .org-tree-node-label {
        -webkit-box-shadow: 0px 2px 12px 0px rgba(143, 154, 165, 0.4);
                box-shadow: 0px 2px 12px 0px rgba(143, 154, 165, 0.4);
        border-radius: 4px;
      }
      .department-outer .view-box .org-tree-wrapper .org-tree-node-label .org-tree-node-label-inner {
        padding: 0;
      }
      .department-outer .view-box .org-tree-wrapper .org-tree-node-label .org-tree-node-label-inner .custom-org-node {
        padding: 14px 41px;
        background: #738699;
        -webkit-user-select: none;
          -moz-user-select: none;
            -ms-user-select: none;
                user-select: none;
        word-wrap: none;
        white-space: nowrap;
        border-radius: 4px;
        color: #ffffff;
        font-size: 14px;
        font-weight: 500;
        line-height: 20px;
        -webkit-transition: background 0.1s ease-in;
        transition: background 0.1s ease-in;
        cursor: default;
      }
      .department-outer .view-box .org-tree-wrapper .org-tree-node-label .org-tree-node-label-inner .custom-org-node:hover {
        background: #5d6c7b;
        -webkit-transition: background 0.1s ease-in;
        transition: background 0.1s ease-in;
      }
      .department-outer .view-box .org-tree-wrapper .org-tree-node-label .org-tree-node-label-inner .custom-org-node.has-children-label {
        cursor: pointer;
      }
      .department-outer .view-box .org-tree-wrapper .org-tree-node-label .org-tree-node-label-inner .custom-org-node .context-menu {
        position: absolute;
        right: -10px;
        bottom: 20px;
        z-index: 10;
      }
      .zoom-wrapper .zoom-button {
        width: 20px;
        height: 20px;
        line-height: 10px;
        border-radius: 50%;
        background: #9da2ac;
        -webkit-box-shadow: 0px 2px 8px 0px rgba(218, 220, 223, 0.7);
                box-shadow: 0px 2px 8px 0px rgba(218, 220, 223, 0.7);
        border: none;
        cursor: pointer;
        outline: none;
        -webkit-transition: all 0.1s ease-in;
        transition: all 0.1s ease-in;
      }
      .zoom-wrapper .zoom-button:active {
        -webkit-box-shadow: 0px 0px 2px 2px rgba(218, 220, 223, 0.2) inset;
                box-shadow: 0px 0px 2px 2px rgba(218, 220, 223, 0.2) inset;
      }
      .zoom-wrapper .zoom-button:hover {
        background: #1890ff;
        -webkit-transition: all 0.1s ease-in;
        transition: all 0.1s ease-in;
      }
      .zoom-wrapper .zoom-number {
        color: #657180;
        padding: 0 8px;
        display: inline-block;
        width: 46px;
        text-align: center;
      }
      .contextmenu {
        position: absolute;
        margin: 0;
        padding: 5px 0;
        background: #fff;
        z-index: 1000;
        border-radius: 4px;
        -webkit-box-shadow: 2px 2px 3px 0 rgba(0, 0, 0, 0.1);
        box-shadow: 2px 2px 3px 0 rgba(0, 0, 0, 0.1);
      }
      .contextmenu ul{
        list-style-type: none;
      }
      .contextmenu li{
        margin: 0;
        padding: 5px 15px;
        cursor: pointer;
      }
      .contextmenu li:hover{
        background: #eee;
      }
    </style>
</head>
<body>
  <div id="app">
    <Card shadow style="height: 100%;width: 100%;overflow:hidden">
      <div class="department-outer">
        <div class="tip-box">
          <b style="margin-right: 20px;">powered by <a target="blank" href="https://github.com/lison16">Lison</a></b>
          <a target="blank" href="https://github.com/lison16/v-org-tree" style="margin-right: 10px;">v-org-tree文档</a>
        </div>
        <div class="zoom-box">
          <div class="zoom-wrapper">
            <button class="zoom-button" @click="scale('down')">
              <Icon type="md-remove" :size="14" color="#fff" />
            </button>
            <span class="zoom-number">{{ zoomValue }}%</span>
            <button class="zoom-button" @click="scale('up')">
              <Icon type="md-add" :size="14" color="#fff" />
            </button>
          </div>
        </div>
        <div class="view-box">
          <div ref="dragWrapper" class="org-tree-drag-wrapper" @mousedown="mousedownView"
            @contextmenu="canMove = false">
            <div class="org-tree-wrapper" :style="orgTreeStyle">
              <v-org-tree v-if="orgData" :data="orgData" :node-render="nodeRender" :expand-all="true"
                @on-node-click="handleNodeClick" collapsable></v-org-tree>
            </div>
          </div>
        </div>
        <div v-show="rightMenuVisible" class="contextmenu" :style="{left: contextMenuLeft + 'px', top: contextMenuTop + 'px'}"
          @mouseout="rightMenuVisible=false">
          <ul>
            <li v-for="(item, index) in menuList" @click="clickContextMenu"
               @mouseover="rightMenuVisible=true">{{item.label}}</li>
          </ul>
        </div>
      </div>
    </Card>
  </div>
</body>

<script>
  var dpData =  {
    id: 0,
    label: 'XXX科技有限公司',
    children: [
      {
        id: 2,
        label: '产品研发部',
        children: [
          {
            id: 5,
            label: '研发-前端'
          }, {
            id: 6,
            label: '研发-后端'
          }, {
            id: 9,
            label: 'UI设计'
          }, {
            id: 10,
            label: '产品经理'
          }
        ]
      },
      {
        id: 3,
        label: '销售部',
        children: [
          {
            id: 7,
            label: '销售一部'
          }, {
            id: 8,
            label: '销售二部'
          }
        ]
      },
      {
        id: 4,
        label: '财务部'
      }, {
        id: 11,
        label: 'HR人事'
      }
    ]
  }

  var menuList = [
  {
    key: 'edit',
    label: '编辑部门'
  },
  {
    key: 'detail',
    label: '查看部门'
  },
  {
    key: 'new',
    label: '新增子部门'
  },
  {
    key: 'delete',
    label: '删除部门'
  }
]

var vm = new Vue({
  el: "#app",
  data: function() {
    return {
      orgData: dpData,
      currentContextMenuId: '',
      orgTreeOffsetLeft: 0,
      orgTreeOffsetTop: 0,
      initPageX: 0,
      initPageY: 0,
      oldMarginLeft: 0,
      oldMarginTop: 0,
      canMove: false,
      zoomValue: 100,
      zoomStep: 20,
      zoomMin: 10,
      zoomMax: 200,
      menuList: menuList,
      rightMenuVisible: false,
      contextMenuLeft: 0,
      contextMenuTop: 0
    }
  },
  computed: {
    orgTreeStyle () {
      return {
        transform: `translate(-50%, -50%) scale(${this.zoomValue/100}, ${this.zoomValue/100})`,
        marginLeft: `${this.orgTreeOffsetLeft}px`,
        marginTop: `${this.orgTreeOffsetTop}px`
      }
    }
  },
  beforeDestroy: function () {
    window.removeEventListener('resize', this.handleResize)
  },
  mounted() {
    window.addEventListener('resize', this.handleResize);
  },
  methods: {
    handleMenuClick ({ data, key }) {
      this.$Message.success({
        duration: 5,
        content: `点击了《${data.label}》节点的'${menuDic[key]}'菜单`
      })
    },
    // 点击节点 打开或收缩
    handleNodeClick (e, data, expand) {
      expand()
    },
    // 绑定节点渲染
    nodeRender (h, data) {
      return h("div", {
          "class": 'custom-org-node ' + ((data.children && data.children.length) ? 'has-children-label' : ''),
          on:{
            mousedown:(event) => {
              event.stopPropagation()
            },
            contextmenu: this.contextmenu.bind(this, data)
          }
      }, [
        data.label   
      ])
    },
    // 显示右键菜单
    contextmenu (data, $event) {
      let event = $event || window.event
      event.preventDefault ? event.preventDefault() : (event.returnValue = false)
      this.contextMenuLeft = event.clientX - 2
      this.contextMenuTop = event.clientY - 2
      this.rightMenuVisible = true
    },
    // 拖动移动 鼠标按下
    mousedownView (event) {
      this.canMove = true
      this.initPageX = event.pageX
      this.initPageY = event.pageY
      this.oldMarginLeft = this.orgTreeOffsetLeft
      this.oldMarginTop = this.orgTreeOffsetTop
      document.addEventListener('mousemove', this.mousemoveView)
      document.addEventListener('mouseup', this.mouseupView)
    },
    // 拖动移动
    mousemoveView (event) {
      if (!this.canMove) return
      const { pageX, pageY } = event
      this.orgTreeOffsetLeft = this.oldMarginLeft + pageX - this.initPageX
      this.orgTreeOffsetTop = this.oldMarginTop + pageY - this.initPageY
    },
    // 拖动移动 鼠标放开
    mouseupView () {
      this.canMove = false
      document.removeEventListener('mousemove', this.mousemoveView)
      document.removeEventListener('mouseup', this.mouseupView)
    },
    // 放大缩小 步长
    scale (type) {
      var zoom = this.zoomValue + (type === 'down' ? -this.zoomStep : this.zoomStep)
      if (zoom >= this.zoomMin && zoom <= this.zoomMax) {
        this.zoomValue = zoom
      }
    },
    clickContextMenu (data, key) {
      // this.$emit('on-menu-click', { data, key })
      debugger
    }
  }
});

</script>
</html> 
